<template>
  <div 
    :class="[
      'bx-transfer',
      'bx-glass',
      {
        [`bx-transfer--${size}`]: size
      }
    ]"
  >
    <div class="bx-transfer__panel">
      <div class="bx-transfer__panel-header">
        <BxCheckbox
          :model-value="allLeftChecked"
          :indeterminate="isLeftIndeterminate"
          :disabled="leftOptions.length === 0"
          @change="handleAllLeftChange"
        />
        <span class="bx-transfer__panel-title">{{ leftTitle }} ({{ leftChecked.length }}/{{ leftOptions.length }})</span>
      </div>
      <div class="bx-transfer__panel-body">
        <ul class="bx-transfer__list">
          <li 
            v-for="option in leftOptions"
            :key="option.value"
            class="bx-transfer__list-item"
          >
            <BxCheckbox
              :model-value="leftChecked.includes(option.value)"
              :disabled="option.disabled"
              @change="handleLeftCheckChange(option.value)"
            />
            <span>{{ option.label }}</span>
          </li>
          <li v-if="leftOptions.length === 0" class="bx-transfer__empty">
            <BxEmpty description="无数据" size="small" />
          </li>
        </ul>
      </div>
    </div>

    <div class="bx-transfer__buttons">
      <BxButton 
        type="primary" 
        :disabled="leftChecked.length === 0"
        @click="moveToRight"
      >
        <BxIcon name="chevron-right" />
      </BxButton>
      <BxButton 
        type="primary" 
        :disabled="rightChecked.length === 0"
        @click="moveToLeft"
      >
        <BxIcon name="chevron-left" />
      </BxButton>
    </div>

    <div class="bx-transfer__panel">
      <div class="bx-transfer__panel-header">
        <BxCheckbox
          :model-value="allRightChecked"
          :indeterminate="isRightIndeterminate"
          :disabled="rightOptions.length === 0"
          @change="handleAllRightChange"
        />
        <span class="bx-transfer__panel-title">{{ rightTitle }} ({{ rightChecked.length }}/{{ rightOptions.length }})</span>
      </div>
      <div class="bx-transfer__panel-body">
        <ul class="bx-transfer__list">
          <li 
            v-for="option in rightOptions"
            :key="option.value"
            class="bx-transfer__list-item"
          >
            <BxCheckbox
              :model-value="rightChecked.includes(option.value)"
              :disabled="option.disabled"
              @change="handleRightCheckChange(option.value)"
            />
            <span>{{ option.label }}</span>
          </li>
          <li v-if="rightOptions.length === 0" class="bx-transfer__empty">
            <BxEmpty description="无数据" size="small" />
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed, watch } from 'vue'
import BxCheckbox from '../input/BxCheckbox.vue'
import BxButton from '../basic/BxButton.vue'
import BxIcon from '../basic/BxIcon.vue'
import BxEmpty from '../data-display/BxEmpty.vue'

export default {
  name: 'BxTransfer',
  components: {
    BxCheckbox,
    BxButton,
    BxIcon,
    BxEmpty
  },
  props: {
    modelValue: {
      type: Array,
      default: () => []
    },
    data: {
      type: Array,
      default: () => []
    },
    leftTitle: {
      type: String,
      default: '源列表'
    },
    rightTitle: {
      type: String,
      default: '目标列表'
    },
    size: {
      type: String,
      default: 'medium',
      validator: (value) => ['small', 'medium', 'large'].includes(value)
    }
  },
  emits: ['update:modelValue', 'change'],
  setup(props, { emit }) {
    const leftChecked = ref([])
    const rightChecked = ref([])

    const leftOptions = computed(() => {
      return props.data.filter(item => !props.modelValue.includes(item.value))
    })

    const rightOptions = computed(() => {
      return props.data.filter(item => props.modelValue.includes(item.value))
    })

    const allLeftChecked = computed(() => {
      return leftOptions.value.length > 0 && leftOptions.value.every(item => leftChecked.value.includes(item.value))
    })

    const isLeftIndeterminate = computed(() => {
      return leftChecked.value.length > 0 && !allLeftChecked.value
    })

    const allRightChecked = computed(() => {
      return rightOptions.value.length > 0 && rightOptions.value.every(item => rightChecked.value.includes(item.value))
    })

    const isRightIndeterminate = computed(() => {
      return rightChecked.value.length > 0 && !allRightChecked.value
    })

    const handleAllLeftChange = (checked) => {
      leftChecked.value = checked ? leftOptions.value.map(item => item.value) : []
    }

    const handleLeftCheckChange = (value) => {
      const index = leftChecked.value.indexOf(value)
      if (index > -1) {
        leftChecked.value.splice(index, 1)
      } else {
        leftChecked.value.push(value)
      }
    }

    const handleAllRightChange = (checked) => {
      rightChecked.value = checked ? rightOptions.value.map(item => item.value) : []
    }

    const handleRightCheckChange = (value) => {
      const index = rightChecked.value.indexOf(value)
      if (index > -1) {
        rightChecked.value.splice(index, 1)
      } else {
        rightChecked.value.push(value)
      }
    }

    const moveToRight = () => {
      const newModelValue = [...props.modelValue, ...leftChecked.value]
      emit('update:modelValue', newModelValue)
      emit('change', newModelValue)
      leftChecked.value = []
    }

    const moveToLeft = () => {
      const newModelValue = props.modelValue.filter(value => !rightChecked.value.includes(value))
      emit('update:modelValue', newModelValue)
      emit('change', newModelValue)
      rightChecked.value = []
    }

    watch(() => props.modelValue, () => {
      leftChecked.value = []
      rightChecked.value = []
    })

    return {
      leftChecked,
      rightChecked,
      leftOptions,
      rightOptions,
      allLeftChecked,
      isLeftIndeterminate,
      allRightChecked,
      isRightIndeterminate,
      handleAllLeftChange,
      handleLeftCheckChange,
      handleAllRightChange,
      handleRightCheckChange,
      moveToRight,
      moveToLeft
    }
  }
}
</script>

<style scoped>
.bx-transfer {
  display: flex;
  align-items: center;
  font-family: var(--bx-font-family);
}

.bx-transfer__panel {
  width: 240px;
  height: 320px;
  border: 1px solid var(--bx-glass-border);
  border-radius: var(--bx-radius-medium);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.bx-transfer__panel-header {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid var(--bx-glass-border);
  background: rgba(255, 255, 255, 0.1);
}

.bx-transfer__panel-title {
  flex: 1;
  margin-left: 8px;
  font-weight: 500;
  color: var(--bx-text-primary);
}

.bx-transfer__panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 8px 0;
}

.bx-transfer__list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.bx-transfer__list-item {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  color: var(--bx-text-secondary);
  transition: background-color var(--bx-transition-fast);
}

.bx-transfer__list-item:hover {
  background: var(--bx-glass-bg-hover);
}

.bx-transfer__list-item .bx-checkbox {
  margin-right: 8px;
}

.bx-transfer__empty {
  text-align: center;
  padding: 24px;
  color: var(--bx-text-tertiary);
}

.bx-transfer__buttons {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 0 16px;
}

.bx-transfer__buttons .bx-button {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.bx-transfer__buttons .bx-button .bx-icon {
  font-size: 18px;
}

/* Size variations */
.bx-transfer--small .bx-transfer__panel {
  width: 200px;
  height: 280px;
}

.bx-transfer--large .bx-transfer__panel {
  width: 280px;
  height: 360px;
}

/* Responsive */
@media (max-width: 768px) {
  .bx-transfer {
    flex-direction: column;
  }
  
  .bx-transfer__buttons {
    flex-direction: row;
    margin: 16px 0;
  }
}
</style>

